<template>
	<view
		class="base-style"
		:style="
			'position: relative;width: ' + diameter + 'rpx;height: ' + diameter + 'rpx;display: flex;flex-direction: row;background-color: ' + bgColor + ';'
		"
	>
		<!-- 左半圆和右半圆都要经历下面的5步:
    [第1步]第1层限定区域; 
    [第2步]第2层决定显示一个整圆的左半边还是右半边; 
    [第3步]第3层先使用激活颜色绘制一个圆环, 再添加一个同级且宽度为区域一半的盒子A;
    [第4步]在盒子A中再使用圆环底色绘制一个圆环, 此时整个圆环是 '左一半是激活颜色、右一半是圆环底色', 但这个圆环同时只能被看到一半;
    [第5步]旋转第2层。 -->

		<!-- 左半圆 -->
		<view class="base-style" :style="firstLayerViewStyle">
			<view :style="secondLayerViewStyle + secondLayerForLeft">
				<!-- 使用激活颜色绘制一个圆环。 -->
				<view :style="thirdLayerStyle"></view>
				<!-- 再使用背景色遮盖同级圆环的一半。 -->
				<view class="base-style" :style="thirdLayerStyleForBg">
					<view :style="fourthLayerStyleForBg" />
				</view>
				<view v-if="0 < ePercent && ePercent < 0.5" :style="endPointStyle + endPointStyleForLeft" />
			</view>
		</view>

		<!-- 右半圆 -->
		<view class="base-style" :style="firstLayerViewStyle">
			<!-- 适配：为了避免右侧遮盖显示不全 此处向左多移动了1px -->
			<view :style="secondLayerViewStyle + 'left: ' + (-diameter / 2 - 1) + 'rpx;' + secondLayerForRight">
				<!-- 使用激活颜色绘制一个圆环。 -->
				<view :style="thirdLayerStyle"></view>
				<!-- 再使用背景色遮盖同级圆环的一半。 -->
				<view class="base-style" :style="thirdLayerStyleForBg">
					<view :style="fourthLayerStyleForBg" />
				</view>
				<view v-if="ePercent > 0.5" :style="endPointStyle + endPointStyleForRight" />
			</view>
		</view>

		<view v-if="0.5 == ePercent" :style="endPointStyle + 'background-color: ' + this.hoopBgColor + ';'" />
		<!-- #ifdef APP-PLUS -->
		<!-- 处理现象: 安卓App的顶部和底部会有一个小白点。 -->
		<!-- <view v-if="ePercent > 0.5" :style="'position: absolute;top: 0;' + repairPointStyle" /> -->
		<!-- <view v-if="1.0 == ePercent" :style="'position: absolute;bottom: 0;' + repairPointStyle" /> -->
		<!-- #endif -->
	</view>
</template>

<script>
export default {
	name: 'CircleProgress',
	props: {
		// 背景色（不宜设置为透明 否则 需要 在 左thirdLayer 的外面 再嵌套一个盒子）。
		bgColor: {
			type: String,
			default: '#FFFFFF'
		},
		// 圆环的外直径（单位rpx）。
		diameter: {
			type: Number,
			default: 250
		},
		// 圆环线条的厚度（单位rpx）。
		hoopThickness: {
			type: Number,
			default: 8
		},
		// 圆环底色（灰色的圆环）。
		hoopBgColor: {
			type: String,
			default: 'transparent'
			// default: "#F3F3F3",
		},
		// 圆环激活部分的颜色。
		hoopColor: {
			type: String,
			default: '#00aa00'
		},
		// 圆环进度百分比值（其值范围在0到1之间）。
		percent: {
			type: [Number, String],
			default: 0,
			validator: (val) => {
				return val >= 0 && val <= 1;
			}
		},
		animate: {
			type: Boolean,
			default: false
		}
	},
	data() {
		return {
			targetPercent: 0,
			ePercent: 0,
			showTimer: undefined
		};
	},
	watch: {
		percent: {
			handler: function () {
				this.loadData();
			}
		}
	},
	computed: {
		firstLayerViewStyle() {
			return 'position: relative;width: ' + this.diameter / 2 + 'rpx;height: ' + this.diameter + 'rpx;';
		},
		secondLayerViewStyle() {
			return 'box-sizing: border-box;position: absolute;top: 0;width: ' + this.diameter + 'rpx;height: ' + this.diameter + 'rpx;';
		},
		thirdLayerStyle() {
			return (
				'box-sizing: border-box;width: ' +
				this.diameter +
				'rpx;height: ' +
				this.diameter +
				'rpx;border-radius: ' +
				this.diameter / 2 +
				'rpx;border-width: ' +
				this.hoopThickness +
				'rpx;border-style: solid;border-color: ' +
				this.hoopColor +
				';'
			);
		},
		thirdLayerStyleForBg() {
			return (
				'box-sizing: border-box;position: absolute;top: 0;left: ' +
				this.diameter / 2 +
				'rpx;width: ' +
				this.diameter +
				'rpx;height: ' +
				this.diameter +
				'rpx;background-color: ' +
				this.bgColor +
				';'
			);
		},
		fourthLayerStyleForBg() {
			return (
				'box-sizing: border-box;margin-left: ' +
				-this.diameter / 2 +
				'rpx;width: ' +
				this.diameter +
				'rpx;height: ' +
				this.diameter +
				'rpx;border-radius: ' +
				this.diameter / 2 +
				'rpx;border-width: ' +
				this.hoopThickness +
				'rpx;border-style: solid;border-color: ' +
				this.hoopBgColor +
				';'
			);
		},
		secondLayerForLeft() {
			let angle = 0;
			if (this.ePercent < 0.5) {
				angle += (180 * (this.ePercent - 0.5)) / 0.5;
			}
			// #ifdef APP-PLUS
			return 'left: 0;transform: rotate(' + angle + 'deg);';
			// #endif
			// #ifndef APP-PLUS
			return 'left: 0;transform: rotate(' + angle + 'deg);-webkit-transform: rotate(' + angle + 'deg);';
			// #endif
		},
		secondLayerForRight() {
			let angle = 0;
			if (this.ePercent > 0.5) {
				angle += (180 * (this.ePercent - 0.5)) / 0.5;
			}
			// #ifdef APP-PLUS
			return 'right: 0;transform: rotate(' + angle + 'deg);';
			// #endif
			// #ifndef APP-PLUS
			return 'right: 0;transform: rotate(' + angle + 'deg);-webkit-transform: rotate(' + angle + 'deg);';
			// #endif
		},
		// repairPointStyle() {
		// 	return 'left: ' + (this.diameter - this.hoopThickness) / 2 + 'px;width: ' +
		// 		this.hoopThickness + 'px;height: ' + this.hoopThickness + 'px;border-radius: ' +
		// 		this.hoopThickness / 2 + 'px;background-color: ' + this.hoopColor + ';';
		// },
		endPointStyle() {
			// 结束点圆心圈直径。
			const _circleCenterRadius = 2;
			return (
				'box-sizing: border-box;position: absolute;top: 0;left: ' +
				(this.diameter - this.hoopThickness) / 2 +
				'rpx;width: ' +
				this.hoopThickness +
				'rpx;height: ' +
				this.hoopThickness +
				'rpx;border-radius: ' +
				this.hoopThickness / 2 +
				'rpx;border-width: ' +
				(this.hoopThickness / 2 - _circleCenterRadius) +
				'rpx;border-style: solid;border-color: ' +
				this.hoopColor +
				';'
			);
		},
		endPointStyleForLeft() {
			return 'background-color: ' + (this.ePercent > 0.5 ? this.hoopColor : this.hoopBgColor) + ';';
		},
		endPointStyleForRight() {
			return 'background-color: ' + (1 == this.ePercent ? this.hoopColor : this.hoopBgColor) + ';';
		}
	},
	data() {
		return {
			targetPercent: 0,
			ePercent: 0,
			showTimer: undefined
		};
	},
	watch: {
		percent: {
			handler: function () {
				this.loadData();
			}
		}
	},
	computed: {
		firstLayerViewStyle() {
			return 'position: relative;width: ' + this.diameter / 2 + 'rpx;height: ' + this.diameter + 'rpx;';
		},
		secondLayerViewStyle() {
			return 'box-sizing: border-box;position: absolute;top: 0;width: ' + this.diameter + 'rpx;height: ' + this.diameter + 'rpx;';
		},
		thirdLayerStyle() {
			return (
				'box-sizing: border-box;width: ' +
				this.diameter +
				'rpx;height: ' +
				this.diameter +
				'rpx;border-radius: ' +
				this.diameter / 2 +
				'rpx;border-width: ' +
				this.hoopThickness +
				'rpx;border-style: solid;border-color: ' +
				this.hoopColor +
				';'
			);
		},
		thirdLayerStyleForBg() {
			return (
				'box-sizing: border-box;position: absolute;top: 0;left: ' +
				this.diameter / 2 +
				'rpx;width: ' +
				this.diameter +
				'rpx;height: ' +
				this.diameter +
				'rpx;background-color: ' +
				this.bgColor +
				';'
			);
		},
		fourthLayerStyleForBg() {
			return (
				'box-sizing: border-box;margin-left: ' +
				-this.diameter / 2 +
				'rpx;width: ' +
				this.diameter +
				'rpx;height: ' +
				this.diameter +
				'rpx;border-radius: ' +
				this.diameter / 2 +
				'rpx;border-width: ' +
				this.hoopThickness +
				'rpx;border-style: solid;border-color: ' +
				this.hoopBgColor +
				';'
			);
		},
		secondLayerForLeft() {
			let angle = 0;
			if (this.ePercent < 0.5) {
				angle += (180 * (this.ePercent - 0.5)) / 0.5;
			}
			// #ifdef APP-PLUS
			return 'left: 0;transform: rotate(' + angle + 'deg);';
			// #endif
			// #ifndef APP-PLUS
			return 'left: 0;transform: rotate(' + angle + 'deg);-webkit-transform: rotate(' + angle + 'deg);';
			// #endif
		},
		secondLayerForRight() {
			let angle = 0;
			if (this.ePercent > 0.5) {
				angle += (180 * (this.ePercent - 0.5)) / 0.5;
			}
			// #ifdef APP-PLUS
			return 'right: 0;transform: rotate(' + angle + 'deg);';
			// #endif
			// #ifndef APP-PLUS
			return 'right: 0;transform: rotate(' + angle + 'deg);-webkit-transform: rotate(' + angle + 'deg);';
			// #endif
		},
		// repairPointStyle() {
		// 	return 'left: ' + (this.diameter - this.hoopThickness) / 2 + 'px;width: ' +
		// 		this.hoopThickness + 'px;height: ' + this.hoopThickness + 'px;border-radius: ' +
		// 		this.hoopThickness / 2 + 'px;background-color: ' + this.hoopColor + ';';
		// },
		endPointStyle() {
			// 结束点圆心圈直径。
			const _circleCenterRadius = 2;
			return (
				'box-sizing: border-box;position: absolute;top: 0;left: ' +
				(this.diameter - this.hoopThickness) / 2 +
				'rpx;width: ' +
				this.hoopThickness +
				'rpx;height: ' +
				this.hoopThickness +
				'rpx;border-radius: ' +
				this.hoopThickness / 2 +
				'rpx;border-width: ' +
				(this.hoopThickness / 2 - _circleCenterRadius) +
				'rpx;border-style: solid;border-color: ' +
				this.hoopColor +
				';'
			);
		},
		endPointStyleForLeft() {
			return 'background-color: ' + (this.ePercent > 0.5 ? this.hoopColor : this.hoopBgColor) + ';';
		},
		endPointStyleForRight() {
			return 'background-color: ' + (1 == this.ePercent ? this.hoopColor : this.hoopBgColor) + ';';
		}
	},
	mounted() {
		this.loadData();
	},
	methods: {
		loadData() {
			this.targetPercent = parseFloat(this.percent);
			if (!this.animate) {
				this.ePercent = this.targetPercent;
			} else {
				let _this = this;
				this.ePercent = 0;
				this.showTimer && clearInterval(this.showTimer);
				this.showTimer = setInterval(() => {
					let tempPercent = _this.ePercent + 0.1;
					if (tempPercent < _this.targetPercent) {
						_this.ePercent = tempPercent;
						return;
					}
					_this.ePercent = _this.targetPercent;
					clearInterval(_this.showTimer);
				}, 200);
			}
		}
	}
};
</script>

<style lang="scss" scoped>
.base-style {
	box-sizing: border-box;
	/* 溢出隐藏 */
	overflow: hidden;
}
</style>
